﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Utility.Inspector.ReorderableList;
using Utility.Inspector;
using System.Linq;
using UnityEditor;
using Utility.Math;

namespace Utility.DataSystem
{
	public class EffectorDrawer
	{
		int allowedVariables;
		int allowedValues;

		ListDrawer listDrawer;

		public EffectorDrawer (int allowedVariables = ~0, int allowedValues = ~0)
		{
			this.allowedVariables = allowedVariables;
			this.allowedValues = allowedValues;

			listDrawer = new ListDrawer (this);
		}

		public void Draw (List<EffectorSettingObject> list)
		{
			listDrawer.Draw (list, ReorderableListFlags.DisableDuplicateCommand | ReorderableListFlags.HideRemoveButtons);
		}

		class ListDrawer : ListDrawer<EffectorSettingObject>
		{
			EffectorDrawer drawer;

			public ListDrawer (EffectorDrawer drawer) : base ()
			{
				this.drawer = drawer;
			}

			protected override EffectorSettingObject CreateItem ()
			{
				var settingObj = new EffectorSettingObject ();
				settingObj.fieldValues.Add (new EffectorSettingObject.FieldValue ());
				return settingObj;
			}

			float w_removeBtn = 25;
			float w_label = 50;
			float w_paramLabel => w_label + 50;

			public override void DrawItem (Rect position, int index)
			{
				EffectorSettingObject effector = List[index];

				//foldout
				Rect pos = position.ResizeHeight (ReorderableListGUI.DefaultItemHeight);
				if (effector != null)
				{
					#region draw variables
					if (effector.variableParams.Count != effector.variables.Count)
					{
						effector.variableParams.Clear ();
						for (int i = 0; i < effector.variables.Count; i++)
						{
							effector.variableParams.Add (new EffectorSettingObject.VariableParams ());
						}
					}

					char varName = 'a';
					var variables = effector.variables;
					for (int i = 0; i < variables.Count; i++)
					{
						Rect pos_line = pos.ShrinkHeight (2);
						EditorGUI.LabelField (pos_line.ResizeWidth (w_label), $"设 {varName} = ");

						//popup
						string variable = variables[i];
						var drawData = FieldCenter.GetDrawData_Variable (drawer.allowedVariables);
						bool invalid = !drawData.keys.Contains (variable);
						using (GUIColorScope.New (invalid, Color.red))
						{
							variables[i] = EditorGUIEX.StringPopupField (pos_line.ShrinkWidth (w_label, w_removeBtn), GUIContent.none, variable, drawData.keys, drawData.shownames);
						}

						//remove btn
						if (GUI.Button (pos_line.DockRight (w_removeBtn), "X"))
						{
							variables.RemoveAt (i);
							break;
						}
						varName++;
						if (varName == 'e')
						{
							varName++;
						}
						pos = pos.ShiftUp ();

						//params
						var fieldSetting = FieldCenter.GetField (variable);
						if (fieldSetting != null)
						{
							effector.variableParams[i].parameters = DrawParam (ref pos, fieldSetting.ParamSettings, effector.variableParams[i]?.parameters);
						}
					}
					#endregion
					#region draw condition
					var conditions = effector.conditions;
					for (int i = 0; i < conditions.Count; i++)
					{
						Rect pos_line = pos.ShrinkHeight (2);
						EditorGUI.LabelField (pos_line.ResizeWidth (w_label), "若");
						//field
						bool invalid = string.IsNullOrWhiteSpace (conditions[i]);
						using (GUIColorScope.New (invalid, Color.red))
						{
							conditions[i] = EditorGUI.TextField (pos_line.ShrinkWidth (w_label, w_removeBtn), conditions[i]);
						}
						//remove btn
						if (GUI.Button (pos_line.DockRight (w_removeBtn), "X"))
						{
							conditions.RemoveAt (i);
							break;
						}
						pos = pos.ShiftUp ();
					}
					#endregion
					#region draw functions
					var fieldValues = effector.fieldValues;
					for (int i = 0; i < fieldValues.Count; i++)
					{
						var field = fieldValues[i];

						Rect pos_line = pos.ShrinkHeight (2);
						EditorGUI.LabelField (pos_line.ResizeWidth (w_label), "值");

						Rect pos_field = pos_line.ShrinkWidth (w_label, w_removeBtn);
						Rect pos_fieldType = pos_field.DivideWidth (2).ShrinkRight (10);
						Rect pos_fieldSeparator = pos_fieldType.ShiftRight ().ResizeWidth (10);
						Rect pos_fieldValue = pos_field.DivideWidth (2).ShiftRight ();

						//popup
						var drawData = FieldCenter.GetDrawData_Value (drawer.allowedValues);
						bool invalid = !drawData.keys.Contains (field.fieldName);
						using (GUIColorScope.New (invalid, Color.red))
						{
							field.fieldName = EditorGUIEX.StringPopupField (pos_fieldType, GUIContent.none, field.fieldName, drawData.keys, drawData.shownames);
						}

						EditorGUI.LabelField (pos_fieldSeparator, "=");
						invalid = string.IsNullOrWhiteSpace (field.expression);
						using (GUIColorScope.New (invalid, Color.red))
						{
							field.expression = EditorGUI.TextField (pos_fieldValue, field.expression);
						}
						//remove btn
						if (GUI.Button (pos_line.DockRight (w_removeBtn), "X"))
						{
							fieldValues.RemoveAt (i);
							break;
						}

						fieldValues[i] = field;
						pos = pos.ShiftUp ();
					}
					#endregion
					#region buttons
					pos = pos.ResizeHeight (ReorderableListGUI.DefaultItemHeight);
					var pos_btn = pos.DockRight (80);
					if (GUI.Button (pos_btn.ShrinkHeight (2), "添加功能"))
					{
						effector.fieldValues.Add (new EffectorSettingObject.FieldValue ());
					}
					pos_btn = pos_btn.ShiftLeft ();
					if (GUI.Button (pos_btn.ShrinkHeight (2), "添加条件"))
					{
						effector.conditions.Add ("");
					}
					pos_btn = pos_btn.ShiftLeft ();
					if (GUI.Button (pos_btn.ShrinkHeight (2), "添加变量"))
					{
						effector.variables.Add ("");
					}
					#endregion
				}

			}

			public override float GetItemHeight (int index)
			{
				float h_line = ReorderableListGUI.DefaultItemHeight;
				EffectorSettingObject setting = List[index];
				float h = h_line;
				foreach (var v in setting.variables)
				{
					h += h_line;

					var f = FieldCenter.GetField (v);
					h += h_line * (f?.ParamCount ?? 0);
				}
				h += h_line * setting.conditions.Count;
				h += h_line * setting.fieldValues.Count;
				return h;
			}

			ActionParam[] DrawParam (ref Rect pos, IList<FieldParamSetting> settingList, ActionParam[] paramList)
			{
				int p_count = settingList.Count;
				if (paramList == null || paramList.Length != p_count)
				{
					paramList = new ActionParam[p_count];
				}

				for (int i = 0; i < settingList.Count; i++)
				{
					var setting = settingList[i];

					var pos_line = pos.ShrinkHeight (2).ShrinkRight (w_removeBtn);
					var pos_label = pos_line.DockLeft (w_paramLabel);
					var pos_expression = pos_line.ShrinkLeft (w_paramLabel);

					string showname = $"[{i}]{(string.IsNullOrWhiteSpace (setting.showName) ? $"参数" : setting.showName)}";
					//label
					EditorGUI.LabelField (pos_label, showname);

					//expression
					var param = paramList[i] ?? (paramList[i] = new ActionParam ());
					bool invalid = string.IsNullOrEmpty (param.str);
					using (GUIColorScope.New (invalid, Color.red))
					{
						if (setting.type.IsSubclassOf (typeof (Setting)))
						{
							param.str = EditorGUIEX.StringPopupField (pos_expression, "", param.str, SettingCenter.GetNameArray (setting.type));
							param.isExpression = false;
						}
						else
						{
							param.str = EditorGUI.TextField (pos_expression, param.str);
							param.isExpression = setting.type != typeof (string);
						}
					}
					pos = pos.ShiftUp ();
				}
				return paramList;
			}
		}
	}
}
